package com.lechuang.file.listener;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *   excel解析监听器
 * </p>
 * @author liaoningbo
 * @since 2023/6/7
*/
@Log4j2
@Data
@NoArgsConstructor
public class AnalysisClassListener<T> extends AnalysisEventListener<T> {
    private Map<Integer, String> headMap = new HashMap<>();
    private List<T> dataList = new ArrayList<>();
    private Class<T> dtoCla;
    private int headRowNumber;

    public AnalysisClassListener(Class<T> dtoCla){
        this.dtoCla = dtoCla;
    }

    public AnalysisClassListener(Class<T> dtoCla, int headRowNumber){
        this.dtoCla = dtoCla;
        this.headRowNumber = headRowNumber;
    }

    /**
     * 读取第一行表头内容
     * @param headMap
     * @param context
     */
    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        for (Map.Entry<Integer, String> integerStringEntry : headMap.entrySet()) {
            if(StrUtil.isNotEmpty(integerStringEntry.getValue())){
                this.headMap.put(integerStringEntry.getKey(), integerStringEntry.getValue());
            }
        }
        ReadRowHolder readRowHolder = context.readRowHolder();
        Integer rowIndex = readRowHolder.getRowIndex();
        if((rowIndex + 1) == this.headRowNumber) {
            List<Field> excelFields = getExcelFields();
            if (this.headMap.size() != excelFields.size()) {
                throw new ExcelAnalysisException("表头检测错误：表头字段数目不正确");
            }
        }
    }

    /**
     * 这个每一条数据解析都会来调用
     */
    @Override
    public void invoke(T model, AnalysisContext context) {
        dataList.add(model);
    }

    /**
     * 所有数据解析完成了 都会来调用
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        log.info("读取完毕！");
    }

    private List<Field> getExcelFields(){
        List<Field> newFields = new ArrayList<>();
        Field[] fields = dtoCla.getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(ExcelProperty.class)){
                newFields.add(field);
            }
        }
        return newFields;
    }
}
